package demo6

import "fmt"

// 组合设计模式
type Component interface {
	// 父
	Parent() Component
	SetParent(Component)
	// 公共方法
	Name() string
	SetName(string)
	// 子
	AddChild(Component)
	//
	Print(string)
}

const (
	LeafNode = iota
	ComponsiteNode
)

func NewComponent(kind int, name string) Component {
	var c Component
	switch kind {
	case LeafNode:
		c = NewLeaf()
	case ComponsiteNode:
		c = NewComponsite()
	}
	c.SetName(name)
	return c
}

type component struct {
	parent Component
	name   string
}

func (c *component) Parent() Component {
	return c.parent
}

func (c *component) SetParent(component Component) {
	c.parent = component
}

func (c *component) Name() string {
	return c.name
}

func (c *component) SetName(name string) {
	c.name = name
}

func (c *component) AddChild(Component) {}
func (c *component) Print(string)       {}

type leaf struct {
	component
}

func NewLeaf() *leaf {
	return &leaf{}
}

func (l *leaf) Print(pre string) {
	fmt.Printf("%s-%s\n", pre, l.Name())
}

type componsite struct {
	component
	childs []Component
}

func NewComponsite() *componsite {
	return &componsite{
		childs: make([]Component, 0),
	}
}

func (c *componsite) SetParent(child Component) {
	child.SetParent(c)
	c.childs = append(c.childs, child)
}

func (c *componsite) Print(pre string) {
	fmt.Printf("%s+%s\n", pre, c.Name())
	pre += " "
	for _, com := range c.childs {
		com.Print(pre)
	}
}
